<?php


namespace app\common\tools;

use think\facade\Env;

class RedisDB
{
    private static $_instance;
    private static $_handler;

    private function __construct()
    {
        $redis = new \Redis();
        $redis->connect(Env::get("REDIS_HOST", '127.0.0.1'), Env::get("REDIS_PORT", '6379'));
        if (Env::get("REDIS_PASS")) {
            $redis->auth(Env::get("REDIS_PASS"));
        }
        $redis->setOption(\Redis::OPT_PREFIX, Env::get("CACHE_PREFIX"));
        $redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP);
        self::$_handler = $redis;

    }

    private function __clone()
    {
        // TODO: Implement __clone() method.
    }

    //出口
    public static function instance()
    {
        if (!(self::$_instance instanceof RedisDB)) {
            self::$_instance = new self;
        }
        return self::$_instance;
    }

    //外部调用
    public function handler()
    {
        return self::$_handler;
    }

    //分布式锁
    public function lock($key, $expire = 2, $try_time = 5)
    {
        $time = time();
        $lock = self::$_handler->setnx($key, $time + $expire);

        if ($lock) { //加锁成功
            self::$_handler->expire($key, $expire + 1);
            return true;
        } else {
            $lockValue = self::$_handler->get($key);
            if ($time >= $lockValue) {  //锁过期，重新加锁
                $lock = self::$_handler->getset($key, $time + $expire);
                if ($lockValue === $lock) { //加锁成功
                    self::$_handler->expire($key, $expire + 1);
                    return true;
                }
            }
        }
        $try_time--;
        if ($try_time <= 0) {
            return false;
        }
        //等待锁过期
        sleep(1);
        return $this->lock($key, $expire, $try_time);
    }

    //释放锁
    public function delLock($key)
    {
        return self::$_handler->del($key);
    }
}
